package com.tangruojie.methodReference;

/**
 * 方法引用是 Lambda 表达式的简写形式，本质是：引用已有的方法来作为函数式接口的实现。
 * ClassName::methodName -> 它的作用是：自动把方法当作 Lambda 函数体来使用。
 */

import com.tangruojie.entity.Author;
import com.tangruojie.entity.Book;
import com.tangruojie.stream.StreamDemoTest;

import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 方法引用使用的前提规则
 * 1、方法引用的参数列表必须和函数式接口的抽象方法参数一致
 * 2、返回值类型也要一致或兼容
 * 3、方法签名匹配即可使用方法引用代替 Lambda
 * 方法引用是 Lambda 的简写形式，只要 Lambda 里是直接调用已有方法，你就可以改成 :: 引用形式。
 */
public class MethodDemo01 {

    public static void main(String[] args) {

        List<Author> authors = StreamDemoTest.getAuthors();

        authors.stream()
                .distinct()
                /**
                 * 类::实例方法
                 * 第一个参数是调用者，其余作为方法参数
                 */
                .map(Author::getAge)
//                .map(new Function<Author, Integer>() {
//                    @Override
//                    public Integer apply(Author author) {
//                        return author.getAge();
//                    }
//                })
                /**
                 * 类::静态方法
                 * 是一个静态方法，且参数个数和类型与接口匹配
                 */
                .map(String::valueOf)
//                .map(new Function<Integer, String>() {
//                    @Override
//                    public String apply(Integer integer) {
//                        return String.valueOf(integer);
//                    }
//                })
                /**
                 * 类名::new
                 * 构造函数的参数与目标接口一致
                 */
                .map(StringBuffer::new)
//                .map(new Function<String, StringBuffer>() {
//                    @Override
//                    public StringBuffer apply(String s) {
//                        return new StringBuffer(s);
//                    }
//                })
                /**
                 * 对象::实例方法
                 * 方法来自已有对象，方法签名与目标接口一致
                 */
                .forEach(System.out::println);
//                .forEach(new Consumer<String>() {
//                    @Override
//                    public void accept(String s) {
//                        System.out.println(s);
//                    }
//                });

    }

}
/**
 * 方法引用的四种常见形式
 * 形式	                说明	                    示例（Lambda）	            示例（方法引用）
 * 1️⃣ 对象::实例方法	    引用某个对象的非静态方法	x -> obj.method(x)	        obj::method
 * 2️⃣ 类::静态方法	    引用类的静态方法	        x -> Class.method(x)	    Class::method
 * 3️⃣ 类::实例方法	    引用任意对象的实例方法	    (a, b) -> a.method(b)	    Class::method
 * 4️⃣ 类名::new	        构造器引用（创建对象）	    () -> new Book()	        Book::new
 */